package com.zt.securityTest.config;


import com.zt.securityTest.filter.JwtAuthenticationTokenFilter;
import com.zt.securityTest.handler.AnonymousAuthenticationHandler;
import com.zt.securityTest.handler.CustomerAccessDeniedHandler;
import com.zt.securityTest.handler.LoginFailureHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * time: 2024.11.15 18:02
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    //认证用户无权限访问资源的处理器
    @Autowired
    private CustomerAccessDeniedHandler customerAccessDeniedHandler;

    //匿名用户无权限访问的处理器
    @Autowired
    private AnonymousAuthenticationHandler anonymousAuthenticationHandler;

    //用户认证校验失败处理器（登录时的报错处理）
    @Autowired
    private LoginFailureHandler loginFailureHandler;

    /**
     * 登陆时需要调用其authenticate方法进行认证
     * @param configuration
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager (AuthenticationConfiguration configuration) throws Exception{
        return configuration.getAuthenticationManager();
    }


    /**
     * 登录请求放行,相当于以前的configure方法
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        //配置关闭csrf机制
        http.csrf(csrf -> csrf.disable());

        //用户认证校验失败处理器（登录时的报错处理）
        http.formLogin(configurer -> configurer.failureHandler(loginFailureHandler));

        //STATELESS(无状态) ：表示应用程序是无状态的，不会创建会话
        http.sessionManagement(configurer ->
                configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        );

        //配置请求拦截
        http.authorizeHttpRequests(auth -> auth.requestMatchers("/users/login")
                .permitAll()
                .anyRequest()
                .authenticated());

        //添加自定义过滤器
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        //添加自定义异常处理器
        http.exceptionHandling(
                //也可以使用链式编程
                configurer -> {
                    configurer.accessDeniedHandler(customerAccessDeniedHandler);
                    configurer.authenticationEntryPoint(anonymousAuthenticationHandler);
                });

        return http.build();
    }

}
